package com.google.gwt.user.rebind.rpc;

import com.google.gwt.core.ext.GeneratorContextExt;
import com.google.gwt.core.ext.GeneratorExt;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.javac.rebind.CachedClientDataMap;
import com.google.gwt.dev.javac.rebind.RebindResult;
import com.google.gwt.dev.javac.rebind.RebindStatus;



/**
 * Generiert anstatt GWT RPC JsonP RPC das eine Cross domain kommunikation erlaubt.
 * 
 * @author wiese.daniel <br>
 *         copyright (C) 2011, SWM Services GmbH
 * 
 */
public class JsonpServiceInterfaceProxyGenerator extends GeneratorExt {

	@Override
	public RebindResult generateIncrementally(TreeLogger logger, GeneratorContextExt ctx, String requestedClass)
		throws UnableToCompleteException {

		TypeOracle typeOracle = ctx.getTypeOracle();
		assert (typeOracle != null);

		JClassType remoteService = typeOracle.findType(requestedClass);
		if (remoteService == null) {
			logger.log(TreeLogger.ERROR, "Unable to find metadata for type '" + requestedClass + "'", null);
			throw new UnableToCompleteException();
		}

		if (remoteService.isInterface() == null) {
			logger.log(TreeLogger.ERROR, remoteService.getQualifiedSourceName() + " is not an interface", null);
			throw new UnableToCompleteException();
		}

		JsonpProxyCreator proxyCreator = createProxyCreator(remoteService);

		TreeLogger proxyLogger = logger
				.branch(TreeLogger.DEBUG,
						"Generating client proxy for remote service interface '"
								+ remoteService.getQualifiedSourceName() + "'", null);

		String returnTypeName = proxyCreator.create(proxyLogger, ctx);

		if (ctx.isGeneratorResultCachingEnabled()) {
			// Remember the type info that we care about for cacheability testing.
			CachedClientDataMap clientData = new CachedClientDataMap();
			proxyCreator.updateResultCacheData(clientData);

			/*
			 * Return with RebindStatus.USE_PARTIAL_CACHED, since we are allowing generator result caching for field
			 * serializers, but other generated types cannot be cached effectively.
			 */
			return new RebindResult(RebindStatus.USE_PARTIAL_CACHED, returnTypeName, clientData);
		} else {
			// If we can't be cacheable, don't return a cacheable result
			return new RebindResult(RebindStatus.USE_ALL_NEW_WITH_NO_CACHING, returnTypeName);
		}
	}



	protected JsonpProxyCreator createProxyCreator(JClassType remoteService) {
		return new JsonpProxyCreator(remoteService);
	}

}
